﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Xc.DataAccess.Core;
using Xc.DataAccess.HyperTerminalCore.Models;
using System.Threading;
using YamlDotNet.Core.Tokens;
using System.Windows;
using System.Windows.Threading;
using System.Diagnostics;

namespace Xc.DataAccess.HyperTerminalCore.Services
{
    /// <summary>
    /// TCP服务 
    /// </summary>
    public class TcpServerService :  ITcpServerService
    {
        /// <summary>
        /// TCP客户端列表
        /// </summary>
        public ObservableCollection<TcpClientInfo> TcpClients { get; set; } = new ObservableCollection<TcpClientInfo>();
        TcpListener IDeviceService;
        public Task<Result> OpenAsync(TcpServerOption option)
        {
            return Task.Run(() => {
                try
                {
                    if (IDeviceService != null)
                    {
                        IDeviceService.Stop();
                    }
                    IDeviceService = new TcpListener(IPAddress.Any, option.Port);
                    IDeviceService.Start();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(AcceptClients));
                    Option = option;
                    return Result.Accept("开启成功");

                }
                catch (Exception err)
                {
                    return Result.Reject(err.Message);
                }
            });

        }
        /// <summary>
        /// 线程分发器
        /// </summary>
        public Dispatcher Dispatcher { get; set; }
        public Action<string> ServerMessage;
        CancellationTokenSource Token = new CancellationTokenSource();
        private  void AcceptClients(object state)
        {
            for (int i = 0; i < 20; i++)
            {
                Task.Run(async() => {
                    while (!Token.IsCancellationRequested)
                    {
                        try
                        {
                            if (IDeviceService.Pending())
                            {
                                var client = await IDeviceService.AcceptTcpClientAsync();
                                var inf = new TcpClientInfo(client, Option.Encoding);
                                inf.OnClose += async (s) =>
                                {
                                    OnClientCloing?.Invoke(s);
                                    Dispatcher?.Invoke(() => {
                                        TcpClients.Remove(s);
                                    });
                                };
                                Debug.WriteLine(inf.IpAddress);
                            AGIAN:

                                if (Dispatcher == null)
                                {
                                    await Task.Delay(100);
                                    goto AGIAN;
                                }
                                Dispatcher?.Invoke(() => {

                                    TcpClients.Add(inf);
                                });


                                inf.BeginRead();
                                OnClientJoin?.Invoke(inf);
                            }
                            else
                            {
                                await Task.Delay(100);
                            }
                        }
                        catch (Exception err)
                        {
                            ServerMessage?.Invoke(err.Message);
                        }
                    }
                });
            }

        }
        private static readonly object _locker = new object(); 
        /// <summary>
        /// 客户端接入时触发
        /// </summary>
        public event Action<TcpClientInfo> OnClientJoin;
        public Result Close()
        {
            try
            {
                Token.Cancel();
                IDeviceService.Stop();
                return Result.Accept("关闭成功");

            }
            catch (Exception err)
            {
                return Result.Reject(err.Message);

            }
        }
        public event Action<TcpClientInfo> OnClientCloing;
        public TcpServerOption Option { get; set; }
    }
}
